\chapter{结构体}

\section{枚举}

\subsection{枚举（Enumeration）}

枚举类型可以将一组相关的常量定义为一个类型，并为这些常量赋予一个可读性较高的名字。枚举类型在定义之后就可以像宏常量一样去使用。\\

例如需要定义一个星期：

\vspace{-0.5cm}

\begin{lstlisting}[language=C++]
enum Weekday {
    SUN, MON, TUE, WED, THU, FRI, SAT
};
\end{lstlisting}

枚举值默认从0开始，因此SUN的值为0、MON的值为1、TUE的值为2，以此类推。\\

当需要指定枚举值时，可以直接在某个枚举常量后赋值，之后的枚举常量的值会在此基础上依次加1。\\

例如需要定义月份：

\vspace{-0.5cm}

\begin{lstlisting}[language=C++]
enum Month {
    JAN = 1, FEB, MAR, APR, MAY, JUN,
    JUL, AUG, SEP, OCT, NOV, DEC,
};
\end{lstlisting}

\newpage

\section{联合体}

\subsection{联合体（Union）}

联合体允许在同一个内存位置存储不同类型的数据，联合体中多个变量共享同一块内存空间，因此联合体所占空间取决于占用空间最大的成员。这意味着在任意时刻，联合体的内存只能用于存储单个成员，这样可以有效节省内存。\\

\mybox{联合体}

\begin{lstlisting}[language=C++]
#include <iostream>

using namespace std;

union Value {
    int int_data;
    char char_data;
};

int main() {
    union Value val;

    val.char_data = 'A';
    cout << "val.int_data = " << val.int_data << endl;

    val.int_data = 97;
    cout << "val.char_data = " << val.char_data << endl;

    return 0;
}
\end{lstlisting}

\begin{tcolorbox}
    \mybox{运行结果}
    \begin{verbatim}
val.int_data = 65
val.char_data = a
	\end{verbatim}
\end{tcolorbox}

\newpage

\section{结构体}

\subsection{结构体（Structure）}

与联合体不同，结构体的成员在内存中占用不同的空间，因此结构体所占空间是所有成员占用空间的总和。\\

结构体通常用于存储复杂的数据类型，将一些相关的变量组合在一起。例如：

\begin{itemize}
    \item 日期（年、月、日）
          \vspace{-0.5cm}
          \begin{lstlisting}[language=C++]
struct Date {
    int year;
    int month;
    int day;
};
    \end{lstlisting}

    \item 坐标（横坐标、纵坐标）
          \vspace{-0.5cm}
          \begin{lstlisting}[language=C++]
struct Coordinate {
    double x;
    double y;
};
    \end{lstlisting}

    \item 学生信息（姓名、出生日期、成绩）
          \vspace{-0.5cm}
          \begin{lstlisting}[language=C++]
struct Student {
    string name;
    struct Date date_of_birth;
    double score;
};
    \end{lstlisting}
\end{itemize}

\vspace{0.5cm}

\subsection{typedef}

typedef用于给数据类型定义别名，通过使用typedef可以简化结构体的声明，不用每次都加上struct关键字了。

\vspace{-0.5cm}
\begin{lstlisting}[language=C++]
typedef struct  {
    int year;
    int month;
    int day;
} Date;

typedef struct {
    string name;
    Date date_of_birth;
    double score;
} Student;
\end{lstlisting}

\vspace{0.5cm}

\subsection{结构体指针}

当结构体变量作为函数参数传递时，如果结构体变量很大，那么会消耗大量时间将结构体变量复制到函数的参数中。\\

为了避免这种情况，可以使用结构体指针作为函数参数，这样只需要将结构体变量的地址传递给函数，函数内部就可以直接访问结构体变量了。\\

使用->运算符可以访问结构体指针所指的结构变量中的成员。\\

\mybox{倒数}

\begin{lstlisting}[language=C++]
#include <iostream>

using namespace std;

typedef struct {
    int numerator;
    int denominator;
} Fraction;

void reciprocal(Fraction *f) {
    if (f->numerator == 0) {
        cerr << "Error: Denominator cannot be zero." << endl;
        exit(1);
    } else {
        int temp = f->numerator;
        f->numerator = f->denominator;
        f->denominator = temp;
    }
}

int main() {
    Fraction fraction = {2, 5};  // 2/5

    cout << "Reciprocal of ";
    cout << fraction.numerator << "/" << fraction.denominator << " is ";
    reciprocal(&fraction);
    cout << fraction.numerator << "/" << fraction.denominator << endl;

    return 0;
}
\end{lstlisting}

\begin{tcolorbox}
    \mybox{运行结果}
    \begin{verbatim}
Reciprocal of 2/5 is 5/2
	\end{verbatim}
\end{tcolorbox}

\newpage